package framework.helpers;

import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import framework.ApplicationManager;
import framework.entities.AppointmentData;

public class PlanningHelper extends BaseHelperForRmis
{
    private int occupiedColumnNumber;

    public PlanningHelper(ApplicationManager app) {
        super(app);
    }
    
	/**
	 * Поиск списка докторов, у которых есть действующее расписание
	 *
	 * @param appointmentData данные для поиска
	 */	
    public void searchService(AppointmentData appointmentData) {
		app.getNavigationHelper().goToPlanning();
    	log.info("Поиск услуги: " + appointmentData);
    	choosePatient(appointmentData.patient);
		chooseMedicalOrganization(appointmentData.medicalOrganization);
		chooseService(appointmentData.service);
		click(By.cssSelector("[title='Найти'] a"));
	}

    private void choosePatient(String patient) {
    	selectFirstInCombobox(By.id("patientId_quickInputContainer"), patient);
    }
	
    private void chooseMedicalOrganization(String medicalOrganization) {
    	if (!medicalOrganization.equals("Контрольная"))
    		selectFirstInCombobox(By.id("organizationIdContainer"), medicalOrganization);
    }
    
    private void chooseService(String service) {
    	click(By.xpath("//*[@id='service.idContainer']/div/div"));
    	typeAndSelectByNumber(By.name("_service.idEdit"), service, 0);
    }
 
	/**
	 * Возвращает количество доступных для выбора докторов
	 *
	 * @return количество найденных докторов
	 */	
	public int countSearchedDoctors() {
		int count = getListOfDoctors().size();
		log.info("count = " + count);
		return count;
	}
	
	private List<WebElement> getListOfDoctors() {
		return findElements(By.cssSelector("#gridview-1016 tr.x-grid-row"));
	}	
 
	/**
	 * Выбирает доктора и свободное время для предварительной записи
	 *
	 * @param appointmentData данные для предварительной записи
	 */	
	public void scheduleAppointment(AppointmentData appointmentData) {
		log.info("Выбор свободного времени " + appointmentData);
		int executorNumber = 0;
		appointmentData.executor = getExecutorName(executorNumber);
		chooseExecutor(executorNumber);
		occupyFreeTime(appointmentData);
	}

	private String getExecutorName(int executorNumber) {
		return getListOfDoctors().get(executorNumber).findElements(By.cssSelector(".x-grid-cell-inner")).get(2).getText();
	}

	private void chooseExecutor(int executorNumber) {
		getListOfDoctors().get(executorNumber).click();
	}	
	
	private void occupyFreeTime(AppointmentData appointmentData) {
		findFreeTime();
		for (int columnNumber = 0; columnNumber < 7; columnNumber++) {
			if (getHeaderInColumn(columnNumber).getAttribute("class").contains("type2") && 
					(!isThereOccupiedTimeInColumn(columnNumber))) {
				occupyTimeInColumn(columnNumber);
				String occupiedTime = getOccupiedCellsInColumn(columnNumber).get(0).findElement(By.className("planning-panel-session-start-time")).getText();				
				appointmentData.setDate(getDateFromHeader(getHeaderInColumn(columnNumber)) + " " + occupiedTime); // dd.MM.yyyy HH:mm
				log.info(appointmentData);
				return;
			}
		}		
	}

	private void findFreeTime() {
		int countIteration = 1000;
		for (int i = 0; i < countIteration && !isThereAnyFreeTime(); i++)
			click(By.id("planningPanel-tbar-page-next-btnEl"));
	}	
	
	private boolean isThereAnyFreeTime() {
		return countElements(By.cssSelector(".planning-panel-can-write-type2:first-child")) > 0;
	}
	
	private WebElement getHeaderInColumn(int columnNumber) {
		return findElements(By.cssSelector(".planning-panel-column-header")).get(columnNumber);
	}
	
	private void occupyTimeInColumn(int columnNumber) {
		WebElement freeTimeCell = getFreeTimes(columnNumber).get(0);
		mainWindow = getWindowHandle();
		dblClick(freeTimeCell);
		closeCouponPage();
		occupiedColumnNumber = columnNumber;
	}
	
	private boolean isThereOccupiedTimeInColumn(int columnNumber) {
		return getOccupiedCellsInColumn(columnNumber).size() > 0;
	}	

	private List<WebElement> getOccupiedCellsInColumn(int columnNumber) {
		return findElements(By.xpath(getColumnItemsXpathLocator(columnNumber) + "/*[contains(@class, 'type1')]"));
	}	
	
	private List<WebElement> getFreeTimes(int columnNumber) {
		return findElements(By.xpath(getColumnItemsXpathLocator(columnNumber) + "/*[contains(@class, 'type2')]"));
	}

	private String getColumnItemsXpathLocator(int columnNumber) {
		return "//*[contains(@class, 'planning-panel-column-item')][" + (columnNumber + 1) + "]";
	}	

	private String getDateFromHeader(WebElement header) {
		return header.getText().split(" ")[0];
	}
	
	private void closeCouponPage() {
		switchToWindow(getNewWindow()).close();
		switchToWindow(mainWindow);
	}

	/**
	 * Возвращает текст выбранной ячейки
	 *
	 * @return текст ячейки
	 */	
	public String getTextOnOccupiedCell() {
		String text = getOccupiedCellsInColumn(occupiedColumnNumber).get(0).getText();
		log.info("text = " + text);
		return text;
	}

	/**
	 * Отменяет запланированную запись
	 *
	 * @param appointmentData данные для поиска
	 */	
	public void cancelAppointment(AppointmentData appointmentData) {
		log.info(appointmentData);
		int executorNumber = 0;
		chooseExecutor(executorNumber);
		cancelBusyTime();
		waitWhileAjaxCompleted();
	}
	
	private void cancelBusyTime() {
		findBusyTime();
		click(By.cssSelector(".planning-panel-can-write-type1"));
		click(By.id("button-1032-btnEl"));
		click(By.cssSelector(".x-form-arrow-trigger"));
		click(By.cssSelector(".x-boundlist-item"));
		click(By.id("button-1071-btnEl"));
	}
	
	private void findBusyTime() {
		int countIteration = 2;
		for (int i = 0; i < countIteration && !isThereAnyBusyTime(); i++)
			click(By.id("planningPanel-tbar-page-next-btnEl"));
	}	
	
	private boolean isThereAnyBusyTime() {
		return countElements(By.cssSelector(".planning-panel-can-write-type1")) > 0;
	}
}
